<template>
  <div class="inline-edit" @click.stop="handleClick" ref="wrapper">
    <input v-model="innerValue" v-if="isEditing" placeholder="文本不能为空" ref="inputRef"
      :class="{ 'input-error': !validateCheck }" class="ant-input" />
    <slot v-else :text="innerValue"><span>{{ innerValue }}</span></slot>
  </div>
</template>

<script lang="ts" setup>
import { ref, watch, computed, nextTick } from 'vue'
import useKeyPress from '../hooks/useKeyPress'
import useClickOutside from '../hooks/useClickOutside'


defineOptions({
  name: 'inline-edit'
})

const props = defineProps({
  value: {
    type: String,
    required: true
  }
})
const emit = defineEmits(['change'])

const innerValue = ref(props.value)
watch(() => props.value, (newValue) => {
  innerValue.value = newValue
})
const wrapper = ref<null | HTMLElement>(null)
const inputRef = ref<null | HTMLInputElement>(null)
const isOutside = useClickOutside(wrapper)
let cachedOldValue = ''
const isEditing = ref(false)
const handleClick = () => {
  isEditing.value = true
}
const validateCheck = computed(() => innerValue.value.trim() !== '')
watch(isEditing, async (isEditing) => {
  if (isEditing) {
    cachedOldValue = innerValue.value
    await nextTick()
    if (inputRef.value) {
      inputRef.value.focus()
    }
  }
})
watch(isOutside, (newValue) => {
  if (!validateCheck.value) {
    return
  }
  if (newValue && isEditing.value) {
    isEditing.value = false
    emit('change', innerValue.value)
  }
  isOutside.value = false
})
useKeyPress('Enter', () => {
  if (!validateCheck.value) {
    return
  }
  if (isEditing.value) {
    isEditing.value = false
    emit('change', innerValue.value)
  }
})
useKeyPress('Escape', () => {
  if (isEditing.value) {
    isEditing.value = false
    innerValue.value = cachedOldValue
  }
})
</script>

<style>
.inline-edit {
  cursor: pointer;
}

.ant-input.input-error {
  border: 1px solid #f5222d;
}

.ant-input.input-error:focus {
  border-color: #f5222d;
}

.ant-input.input-error::placeholder {
  color: #f5222d;
}
</style>
